<template>
  <el-drawer v-model="drawerVisible" :destroy-on-close="true" size="90%" :title="`${drawerProps.title}-表配置`">
    <el-form
      ref="ruleFormRef"
      label-width="100px"
      label-suffix=" :"
      :rules="rules"
      :disabled="drawerProps.isView"
      :model="dataInfo"
      :hide-required-asterisk="drawerProps.isView"
      :inline="true"
      class="form-inline"
    >
      <el-form-item label="表名" prop="tableName">
        <el-select
          :disabled="!drawerProps.isSave"
          v-model="dataInfo.tableName"
          filterable
          placeholder="选择表名"
          @change="changeTableName"
          clearable
        >
          <el-option v-for="option in tableNameOptions" :key="option" :value="option" :label="option" />
        </el-select>
      </el-form-item>
      <el-form-item label="表注释" prop="comment">
        <el-input v-model="dataInfo.comment" placeholder="表注释可修改" clearable></el-input>
      </el-form-item>
      <el-form-item label="表前缀" prop="tablePrefix">
        <template #label>
          <el-space>
            <span>表前缀</span>
            <el-tooltip effect="dark" content="如果填写了表前缀，生成时表名会主动去除表前缀" placement="top">
              <i :class="'iconfont icon-yiwen'"></i>
            </el-tooltip>
          </el-space>
          <span>&nbsp;:</span>
        </template>
        <el-input v-model="dataInfo.tablePrefix" placeholder="表前缀" clearable></el-input>
      </el-form-item>
      <el-form-item label="实体父类" prop="superClass">
        <el-select v-model="dataInfo.superClass" style="width: 400px" filterable placeholder="选择一个父类" clearable>
          <el-option v-for="option in superClassOptions" :key="option" :value="option" :label="option" />
        </el-select>
      </el-form-item>
      <el-form-item label="包名" prop="packageName">
        <template #label>
          <el-space>
            <span>包名</span>
            <el-tooltip effect="dark" content="最终的包名为: 包名.模块名" placement="top">
              <i :class="'iconfont icon-yiwen'"></i>
            </el-tooltip>
          </el-space>
          <span>&nbsp;:</span>
        </template>
        <el-input v-model="dataInfo.packageName" placeholder="包名" clearable></el-input>
      </el-form-item>
      <el-form-item label="模块名" prop="moduleName">
        <el-input v-model="dataInfo.moduleName" placeholder="模块名" clearable></el-input>
      </el-form-item>
      <el-form-item label="作者" prop="author">
        <el-input v-model="dataInfo.author" placeholder="作者" clearable></el-input>
      </el-form-item>
    </el-form>
    <!--  列配置  -->
    <ProTable :pagination="false" :tool-button="false" :data="dataInfo.columnConfigList" :columns="columns">
      <template #tableHeader>
        <el-form inline>
          <el-form-item label="分页接口">
            <el-switch v-model="dataInfo.genPage" class="ml-2" inline-prompt active-text="生成" inactive-text="不生成" />
          </el-form-item>
          <el-form-item label="信息接口">
            <el-switch v-model="dataInfo.genInfo" class="ml-2" inline-prompt active-text="生成" inactive-text="不生成" />
          </el-form-item>
          <el-form-item label="新增接口">
            <el-switch
              v-model="dataInfo.genSave"
              @change="openFormTypeColumn"
              class="ml-2"
              inline-prompt
              active-text="生成"
              inactive-text="不生成"
            />
          </el-form-item>
          <el-form-item label="更新接口">
            <el-switch
              v-model="dataInfo.genUpdate"
              @change="openFormTypeColumn"
              class="ml-2"
              inline-prompt
              active-text="生成"
              inactive-text="不生成"
            />
          </el-form-item>
          <el-form-item label="删除接口">
            <el-switch v-model="dataInfo.genDeleted" class="ml-2" inline-prompt active-text="生成" inactive-text="不生成" />
          </el-form-item>
          <el-form-item label="导入接口">
            <el-switch v-model="dataInfo.genImport" class="ml-2" inline-prompt active-text="生成" inactive-text="不生成" />
          </el-form-item>
          <el-form-item label="导出接口">
            <el-switch v-model="dataInfo.genExport" class="ml-2" inline-prompt active-text="生成" inactive-text="不生成" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" v-if="drawerProps.isUpdate" :icon="Refresh" @click="refreshInfo">刷新表结构</el-button>
          </el-form-item>
        </el-form>
      </template>
      <template #fieldType="scope">
        <el-select
          :disabled="drawerProps.isView"
          v-model="scope.row.enumDictType"
          filterable
          :placeholder="scope.row.fieldType"
          @focus="focusEnumDictType(scope.row.fieldType)"
          clearable
        >
          <template #header>默认字段类型:{{ scope.row.fieldType }}</template>
          <el-option v-for="option in enumDictTypeOptions" :key="option.name" :value="option.name" :label="option.name" />
        </el-select>
      </template>
      <template #required="scope">
        <el-switch v-model="scope.row.required" inline-prompt active-text="是" inactive-text="否" />
      </template>
      <template #showInList="scope">
        <el-switch
          :disabled="scope.row.columnPk || drawerProps.isView"
          v-model="scope.row.showInList"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
      <template #showInQuery="scope">
        <el-switch
          :disabled="drawerProps.isView"
          v-model="scope.row.showInQuery"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
      <template #queryType="scope">
        <el-select
          :disabled="drawerProps.isView"
          v-if="scope.row.showInQuery"
          v-model="scope.row.queryType"
          filterable
          placeholder="选择查询类型"
          clearable
        >
          <el-option v-for="option in queryTypeOptions" :key="option.label" :value="option.value" :label="option.label" />
        </el-select>
        <div v-else>--</div>
      </template>
      <template #showInInfo="scope">
        <el-switch
          :disabled="scope.row.columnPk || drawerProps.isView"
          v-model="scope.row.showInInfo"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
      <template #showInSave="scope">
        <el-switch
          :disabled="drawerProps.isView"
          v-model="scope.row.showInSave"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
      <template #showInUpdate="scope">
        <el-switch
          :disabled="scope.row.columnPk || drawerProps.isView"
          v-model="scope.row.showInUpdate"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
      <template #formType="scope">
        <el-select
          :disabled="scope.row.columnPk || drawerProps.isView"
          v-if="scope.row.showInSave || scope.row.showInUpdate"
          v-model="scope.row.formType"
          filterable
          placeholder="选择表单类型"
          clearable
        >
          <el-option v-for="option in formTypeOptions" :key="option.label" :value="option.value" :label="option.label" />
        </el-select>
        <div v-else>--</div>
      </template>
      <template #showInImport="scope">
        <el-switch
          :disabled="drawerProps.isView"
          v-model="scope.row.showInImport"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
      <template #showInExport="scope">
        <el-switch
          :disabled="drawerProps.isView"
          v-model="scope.row.showInExport"
          inline-prompt
          active-text="是"
          inactive-text="否"
        />
      </template>
    </ProTable>
    <template #footer>
      <el-button @click="drawerVisible = false">取消</el-button>
      <el-button v-show="!drawerProps.isView" type="primary" @click="handleSubmit">确定</el-button>
    </template>
  </el-drawer>
</template>

<script setup lang="tsx">
import { reactive, ref, toRef } from "vue";
import { ElMessage, FormInstance } from "element-plus";
import {
  ColumnConfigSaveOrUpdateParams,
  GenPageResult,
  getSuperClassOptions,
  getTableNameOptions,
  loadTableInfo,
  tableConfigInfo,
  TableConfigSaveOrUpdateParams
} from "@/api/modules/generator";
import ProTable from "@/components/ProTable/index.vue";
import { ColumnProps, FieldNamesProps, HeaderRenderScope } from "@/components/ProTable/interface";
import { EnumListResults, getEnumDictItem, getEnumList } from "@/api/modules/sys/dict";
import { Refresh } from "@element-plus/icons-vue";

const rules = reactive({
  tableName: [{ required: true, message: "请选择数据表" }],
  superClass: [{ required: true, message: "请选择实体父类" }],
  packageName: [{ required: true, message: "请输入包名" }],
  moduleName: [{ required: true, message: "请输入模块名" }]
});

interface DrawerProps {
  title: string;
  isView: boolean;
  isSave: boolean;
  isUpdate: boolean;
  row: Partial<GenPageResult>;
  api?: (params: any) => Promise<any>;
  getTableList?: () => void;
}

const drawerVisible = ref(false);
const drawerProps = ref<DrawerProps>({
  isView: false,
  isSave: false,
  isUpdate: false,
  title: "",
  row: {}
});

const dataInfo = ref<TableConfigSaveOrUpdateParams>({
  genPage: false,
  genInfo: false,
  genSave: false,
  genUpdate: false,
  genDeleted: false,
  genImport: false,
  genExport: false
});

// 这是为了解决表单类型列展示的问题，它是新增和更新两个开关控制
const openForm = ref<boolean>(dataInfo.value.genSave || dataInfo.value.genUpdate);
const openFormTypeColumn = () => {
  openForm.value = dataInfo.value.genSave || dataInfo.value.genUpdate;
};

// 列的表格
const columns = reactive<ColumnProps[]>([
  {
    prop: "columnName",
    label: "列名"
  },
  {
    prop: "comment",
    label: "列注释",
    width: "150px"
  },
  {
    prop: "columnPk",
    label: "主键列"
  },
  {
    prop: "columnTypeName",
    label: "列类型"
  },
  {
    prop: "fieldName",
    label: "字段名"
  },
  {
    prop: "fieldType",
    label: "字段类型",
    width: "150px",
    headerRender: scope => headerRender({ ...scope, tooltip: "如果字段应该是枚举，请选择对应的枚举(可搜索)" })
  },
  {
    prop: "required",
    label: "必填",
    headerRender: scope => headerRender({ ...scope, tooltip: "是否在保存接口或者更新接口进行校验" })
  },
  {
    prop: "showInList",
    label: "分页",
    isShow: toRef(dataInfo.value, "genPage"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否在分页接口中出现" })
  },
  {
    prop: "showInQuery",
    label: "查询",
    isShow: toRef(dataInfo.value, "genPage"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否可以作为分页的查询条件" })
  },
  {
    prop: "queryType",
    label: "查询类型",
    width: "150px",
    isShow: toRef(dataInfo.value, "genPage")
  },
  {
    prop: "showInInfo",
    label: "信息",
    isShow: toRef(dataInfo.value, "genInfo"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否出现在信息接口(更新时进行回显)" })
  },
  {
    prop: "showInSave",
    label: "保存",
    isShow: toRef(dataInfo.value, "genSave"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否出现在保存接口" })
  },
  {
    prop: "showInUpdate",
    label: "更新",
    isShow: toRef(dataInfo.value, "genUpdate"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否出现在更新接口" })
  },
  {
    prop: "formType",
    label: "表单类型",
    width: "150px",
    isShow: openForm,
    headerRender: scope => headerRender({ ...scope, tooltip: "保存或更新的表单样式" })
  },
  {
    prop: "showInImport",
    label: "导入",
    isShow: toRef(dataInfo.value, "genImport"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否可导入" })
  },
  {
    prop: "showInExport",
    label: "导出",
    isShow: toRef(dataInfo.value, "genExport"),
    headerRender: scope => headerRender({ ...scope, tooltip: "是否可导出" })
  }
]);

const headerRender = (scope: HeaderRenderScope<ColumnConfigSaveOrUpdateParams>) => {
  return (
    <div>
      <span>{scope.column.label}</span>
      <el-tooltip effect="dark" content={scope.tooltip} placement="top">
        <i class="iconfont icon-yiwen" style="margin-left: 5px" />
      </el-tooltip>
    </div>
  );
};

// 可以下拉选择表名
const tableNameOptions = ref<string[]>([]);
// 下拉选择父类
const superClassOptions = ref<string[]>([]);
// 查询类型
const queryTypeOptions = ref<FieldNamesProps[]>([]);
// 表单类型
const formTypeOptions = ref<FieldNamesProps[]>([]);
// 接收父组件传过来的参数
const acceptParams = async (params: DrawerProps) => {
  if (params.row.id) {
    let { data } = await tableConfigInfo(params.row.id, false);
    dataInfo.value = Object.assign(dataInfo.value, data);
  } else {
    dataInfo.value = Object.assign(dataInfo.value, {
      id: null,
      tableName: null,
      comment: null,
      author: null,
      moduleName: null,
      packageName: null,
      superClass: null,
      tablePrefix: null,
      genPage: false,
      genInfo: false,
      genSave: false,
      genUpdate: false,
      genDeleted: false,
      genImport: false,
      genExport: false,
      columnConfigList: []
    });
    // 新增需要获取可选表名
    let { data } = await getTableNameOptions();
    tableNameOptions.value = data;
  }
  if (!params.isView) {
    // 表单类型这列单独判断一下是否需要显示
    openFormTypeColumn();
    let { data } = await getSuperClassOptions();
    superClassOptions.value = data;

    let queryTypeResult = await getEnumDictItem("QueryType");
    queryTypeOptions.value = queryTypeResult.data;

    let formTypeResult = await getEnumDictItem("FormType");
    formTypeOptions.value = formTypeResult.data;
  }
  drawerProps.value = params;
  drawerVisible.value = true;
};

// 刷新数据表
const refreshInfo = async () => {
  if (dataInfo.value.id) {
    let { data } = await tableConfigInfo(dataInfo.value.id, true);
    dataInfo.value = Object.assign(dataInfo.value, data);
  }
};

// 改变表触发的事件
const changeTableName = async (tableName: string) => {
  let { data } = await loadTableInfo(tableName);
  dataInfo.value.tablePrefix = data.tablePrefix;
  dataInfo.value.comment = data.comment;
  if (data.tablePrefix && data.tablePrefix !== "") {
    dataInfo.value.moduleName = data.tablePrefix;
  }
  // 设置列信息
  dataInfo.value.columnConfigList = [];
  for (let columnInfo of data.columnInfoList) {
    dataInfo.value.columnConfigList.push({
      id: null,
      enumDictType: null,
      ...columnInfo,
      showInList: columnInfo.columnPk,
      showInQuery: false,
      queryType: null,
      showInInfo: columnInfo.columnPk,
      showInSave: false,
      showInUpdate: columnInfo.columnPk,
      formType: null,
      showInImport: false,
      showInExport: false
    });
  }
};

const enumDictTypeOptions = ref<EnumListResults[]>([]);

const focusEnumDictType = async (fieldType: string) => {
  let { data } = await getEnumList({ valueType: fieldType, standard: true });
  enumDictTypeOptions.value = data;
};

// 提交数据（新增/编辑）
const ruleFormRef = ref<FormInstance>();
const handleSubmit = () => {
  ruleFormRef.value!.validate(async valid => {
    if (!valid) return;
    try {
      await drawerProps.value.api!(dataInfo.value);
      ElMessage.success({ message: `${drawerProps.value.title} 成功！` });
      drawerProps.value.getTableList!();
      drawerVisible.value = false;
    } catch (error) {
      console.log(error);
    }
  });
};

defineExpose({
  acceptParams
});
</script>

<style scoped lang="scss">
.form-inline .el-input {
  --el-input-width: 220px;

  width: 220px;
}
.form-inline .el-select {
  --el-select-width: 220px;

  width: 220px;
}
</style>
